package org.jiamandan.com.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.extra.spring.SpringUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jiamandan.com.cache.CacheNames;
import org.jiamandan.com.config.TcpInboundAdapter;
import org.jiamandan.com.constant.BizConstant;
import org.jiamandan.com.constant.JSYConstant;
import org.jiamandan.com.entity.RechargePile;
import org.jiamandan.com.service.IRechargePileService;
import org.jiamandan.com.utils.CommonUtil;
import org.jiamandan.com.utils.IdentityIdUtil;
import org.jiamandan.com.utils.RedisUtil;
import org.jiamandan.com.utils.ZDObjectUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Map;

@Service
@Slf4j
public class RechargePileServiceImpl implements IRechargePileService {
    RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);

    @Override
    public void testJsy2charge(String pileNo, String gunNo, Integer isOpen) {
        BigDecimal chargeAmt = new BigDecimal(0);
        long id = IdentityIdUtil.getFlowIdInstance().nextId();
        String orderNo = String.valueOf(id);
        Channel channel = getChannel(pileNo);
        if(channel==null){
            throw new RuntimeException("channel不能为空");
        }
        StringBuilder payload = new StringBuilder();
        payload.append("00")//费率模式  、余额模式
                .append(CommonUtil.reverseHex(StringUtils.leftPad(Integer.toHexString(chargeAmt.multiply(BigDecimal.valueOf(100)).intValue()), 8, "0")))
                    .append(StringUtils.leftPad(String.valueOf(NumberUtil.toInt(gunNo.getBytes()) - 1), 2, "0")) //端口号
                //充电命令=0(停止充电)，=1(开始充电)设备充电与否依据此字段
                .append(StringUtils.leftPad(String.valueOf(isOpen), 2, "0"))    //充电的命令
                .append("0000")     //充电时长
                .append(StringUtils.leftPad("746974540608835584", 32, "0"))
                //最大充电时长 先按照 最高功率计算费用下发最大时间，后06指令获取实际最高功率重新计算时间08指令下发
                .append(CommonUtil.reverseHex(StringUtils.leftPad(Integer.toHexString(30), 4, "0")))
                //最大1000功率
                .append(CommonUtil.reverseHex(StringUtils.leftPad(Integer.toHexString(900 * 10), 4, "0")))
                .append("01")
                .append("00")
                .append("0000");//额外增加的浮充时间，单位秒，如果下发的是0xFFFF，则为取消浮充
        RechargePile pile = new RechargePile();
        pile.setCode(4);
        pile.setPileNo(pileNo);
        String replyMsg = ZDObjectUtil.ydsplicingMessage(payload.toString(), pile, gunNo, BizConstant.Cmd.CMD_YD_82);
        log.info("嘉满电-YD下发充电或停止(CMD=82)设备号【" + pile.getPileNo() + "】报文:" + replyMsg);
        ByteBuf buf = Unpooled.buffer(replyMsg.getBytes().length);
        buf.writeBytes(CommonUtil.hexToByteArray(replyMsg));
        ChannelFuture future = channel.writeAndFlush(buf);
        log.info("JMD-2口测试={}",replyMsg);
        log.info("下发充电={}",future.isSuccess());
    }

    @Override
    public void testJsy10charge(String pileNo, String gunNo, Integer isOpen) {
        long id = IdentityIdUtil.getFlowIdInstance().nextId();
        String orderNo = String.valueOf(id);
        Channel channel = getChannel(pileNo);
        if(channel==null){
            throw new RuntimeException("channel不能为空");
        }
        if(isOpen>0){
            Integer maxChargeTime = 10;                  //最大充电时间(分钟)
            StringBuilder builder = new StringBuilder();
            builder.append("_" + JSYConstant.Cmd.S00201).append("/0027:");
            builder.append(gunNo + "/")
                    .append(StringUtils.leftPad(String.valueOf(maxChargeTime), 4, "0"))
                    .append("/")
                    .append(StringUtils.leftPad(Long.toHexString(Long.valueOf(orderNo)), 16, "0"))
                    .append("/02") //刷卡01或者服务器命令02
                    .append("\r\n");
            log.info("JMD-4/10口测试={}",builder.toString());
            ByteBuf buf = Unpooled.buffer(builder.toString().getBytes().length);
            buf.writeBytes(builder.toString().getBytes());
            ChannelFuture future = channel.writeAndFlush(buf);
            System.out.println(future);
        }else{
            //下发停止充电
            StringBuilder builder = new StringBuilder();
            builder.append("_"+ JSYConstant.Cmd.S00203).append("/0002:");
            builder.append(gunNo)
                    .append("\r\n");
            log.info("嘉满电-JSY设备号：【" + pileNo + "】停止充电(CMD = S00203):" + builder.toString());
            ByteBuf buf = Unpooled.buffer(builder.toString().getBytes().length);
            buf.writeBytes(builder.toString().getBytes());
            ChannelFuture future = channel.writeAndFlush(buf);
        }
    }


    @Override
    public void testJsy2Time(String pileNo, String gunNo) {
        RechargePile pile = new RechargePile();
        Channel channel = getChannel(pileNo);
        if(channel==null){
            throw new RuntimeException("channel不能为空");
        }
        pile.setCode(4);
        pile.setPileNo(pileNo);
        StringBuilder payload = new StringBuilder();
        payload.append("01")
                .append(gunNo)
                .append(CommonUtil.reverseHex(StringUtils.leftPad(Integer.toHexString(0),4,"0")));
        String replyMsg = ZDObjectUtil.ydsplicingMessage(payload.toString(), pile, gunNo, BizConstant.Cmd.CMD_YD_8a);
        ByteBuf buf = Unpooled.buffer(replyMsg.getBytes().length);
        buf.writeBytes(CommonUtil.hexToByteArray(replyMsg));
        ChannelFuture future = channel.writeAndFlush(buf);
        log.info("JMD-2口测试修改时长={}",replyMsg);
        log.info("下发充电={}",future.isSuccess());
    }

    @Override
    public String testJsy10online(String pileNo) {
        Channel channel = getChannel(pileNo);
        if(channel==null){
            return "未在线";
        }
        return "在线";
    }

    @Override
    public String getJsy10Info(String pileNo) {
        Channel channel = getChannel(pileNo);
        StringBuilder builder = new StringBuilder();
        builder.append("_" + JSYConstant.Cmd.S00008).append("/0018:");
        builder.append(pileNo)
                .append("/00")
                .append("\r\n");
        ByteBuf buf = Unpooled.buffer(builder.toString().getBytes().length);
        buf.writeBytes(builder.toString().getBytes());
        ChannelFuture future = channel.writeAndFlush(buf);
        log.info("嘉满电-JSY设备号：【" + pileNo + "】下发获取信息(CMD = S00008):" + builder.toString());
        return String.valueOf(future.isSuccess());
    }


    private Channel getChannel(String pileNo) {
        Map<String, ChannelId> channels = (Map<String, ChannelId>) redisUtil.get(CacheNames.TCP_CHANNEL);
        if (channels == null || channels.get(pileNo) == null) {
            log.error(pileNo + ":未找到相关发送通道ID");
            return null;
        }
        log.info("==========" + channels.get(pileNo) + "------" + pileNo + "=============");
        ChannelId channelId = channels.get(pileNo);
        Channel channel = TcpInboundAdapter.clients.find(channelId);
        if (channel == null) {
            log.error(pileNo + ":未找到相关发送通道");
            return null;
        }
        log.error("设备号:" + pileNo + "channel:" + channel.id() + "是否active:" + channel.isActive());
        return channel;
    }
}
